## generic imports
import altair as alt
import pandas as pd
from vega_datasets import data
import glob
from os import listdir,path
from pathlib import Path

counties = alt.topo_feature(data.us_10m.url, 'counties')
# used for world visualization later
#countries = alt.topo_feature(data.world_110m.url, 'countries')
source = data.unemployment.url

#https://altair-viz.github.io/user_guide/faq.html
alt.data_transformers.disable_max_rows()

# https://altair-viz.github.io/user_guide/transform/lookup.html
#### month selection
month_select = alt.selection_single(
    name='select', fields=['date'], init={'monthdate(date)':1},
    bind=alt.binding_range(min=1, max=12, step =1)
)

### to add animation to chloropleth map, start the data with your data frame and then use lookup on the url, as altair can't
### dynamically resolve which data to animate and it can only do it with pd dataframes

directory_in_str = './COVID-19-master/csse_covid_19_data/csse_covid_19_daily_reports_us/'
def find_csv_filenames( path_to_dir, suffix):
    filenames = listdir(path_to_dir)
    return [ filename for filename in filenames if filename.endswith( suffix ) ]

# create clustering algorithm to cluster states into the 5 regions
def fiveRegion(statename):

#     West]Colorado, Wyoming, Montana, Idaho, Washington, Oregon, Utah, Nevada, California, Alaska, Hawaii


    regionName = ""
    if statename == 'Alabama':
        regionName = 'Southeast'
        
    elif statename == 'Alaska':
        regionName = 'West'
        
    elif statename == 'Arizona':
        regionName = 'Southwest'
        
    elif statename == 'Arkansas':
        regionName = 'Southeast'
        
    elif statename == 'California':
        regionName = 'West'
        
    elif statename == 'Colorado':
        regionName = 'West'
        
    elif statename == 'Connecticut':
        regionName = 'Northeast'
        
    elif statename == 'Delaware':
        regionName = 'Northeast'
        
#     elif statename == 'District of Columbia':
#         regionName = 'West'
    
    elif statename == 'Florida':
        regionName = 'Southeast'
    
    elif statename == 'Georgia':
        regionName = 'Southeast'
    
    elif statename == 'Hawaii':
        regionName = 'West'
    
    elif statename == 'Idaho':
        regionName = 'West'
    
    elif statename == 'Illinois':
        regionName = 'Midwest'
    
    elif statename == 'Indiana':
        regionName = 'Midwest'
    
    elif statename == 'Iowa':
        regionName = 'Midwest'
    
    elif statename == 'Kansas':
        regionName = 'Midwest'
    
    elif statename == 'Kentucky':
        regionName = 'Southeast'
    
    elif statename == 'Louisiana':
        regionName = 'Southeast'
    
    elif statename == 'Maine':
        regionName = 'Northeast'
    
    elif statename == 'Maryland':
        regionName = 'Northeast'
    
    elif statename == 'Massachusetts':
        regionName = 'Northeast'
    
    elif statename == 'Michigan':
        regionName = 'Midwest'
    
    elif statename == 'Minnesota':
        regionName = 'Midwest'
    
    elif statename == 'Mississippi':
        regionName = 'Southeast'
    
    elif statename == 'Missouri':
        regionName = 'Midwest'
    
    elif statename == 'Montana':
        regionName = 'West'
    
    elif statename == 'Nebraska':
        regionName = 'Midwest'
    
    elif statename == 'Nevada':
        regionName = 'West'
    
    elif statename == 'New Hampshire':
        regionName = 'Northeast'
    
    elif statename == 'New Jersey':
        regionName = 'Northeast'
    
    elif statename == 'New Mexico':
        regionName = 'Southwest'
    
    elif statename == 'New York':
        regionName = 'Northeast'
    
    elif statename == 'North Carolina':
        regionName = 'Southeast'
    
    elif statename == 'North Dakota':
        regionName = 'Midwest'
    
#     elif statename == 'Northern Mariana Islands':
    
    elif statename == 'Ohio':
        regionName = 'Midwest'
    
    elif statename == 'Oklahoma':
        regionName = 'Southwest'
    
    elif statename == 'Oregon':
        regionName = 'West'
    
    elif statename == 'Pennsylvania':
        regionName = 'Northeast'
    
    elif statename == 'Rhode Island':
        regionName = 'Northeast'
    
    elif statename == 'South Carolina':
        regionName = 'Southeast'
    
    elif statename == 'South Dakota':
        regionName = 'Midwest'
    
    elif statename == 'Tennessee':
        regionName = 'Southeast'
    
    elif statename == 'Texas':
        regionName = 'Southwest'
    
    elif statename == 'Utah':
        regionName = 'West'
    
    elif statename == 'Vermont':
        regionName = 'Northeast'
    
#     elif statename == 'Virgin Islands':
    
    elif statename == 'Virginia':
        regionName = 'Southeast'
    
    elif statename == 'Washington':
        regionName = 'West'
    
    elif statename == 'West Virginia':
        regionName = 'Southeast'
    
    elif statename == 'Wisconsin':
        regionName = 'Midwest'
    
    elif statename == 'Wyoming':
        regionName = 'West'
    
    else:
        regionName = 'Not a region'
        
    
    return regionName

# open covid 'csse_covid_19_daily_reports_us'
filePath = './COVID-19-master/csse_covid_19_data/csse_covid_19_daily_reports_us/01-01-2021.csv'
filename = path.basename('/csse_covid_19_daily_reports_us/01-01-2021.csv')
# filePath = str(filePath)
print(filename)
df = pd.read_csv('%s' % filePath)
df["date"] = filename.replace('.csv','')
# df.to_csv("{filename}.csv", index=False)

# list comprehensions
df['region'] = [fiveRegion(x) for x in df['Province_State']]
df['FIPS'] = [int(x) for x in df['FIPS']]

# cleanup
df = df.rename({"Province_State": "State", "Country_Region":"Country"}, axis='columns')
df.shape
01-01-2021.csv
(58, 20)

# Delete rows where region is 'not a region'
# This deletion is completed by "selecting" rows where regions are non 'not a region'
df = df.loc[df["region"] != 'Not a region']
df.shape
(50, 20)

csvlist21 = find_csv_filenames(directory_in_str, "2021.csv")
csvlist20 = find_csv_filenames(directory_in_str, "2020.csv")
csvlist21new = [directory_in_str + s for s in csvlist21]
csvlist20new = [directory_in_str + s for s in csvlist20]
# print(csvlist)

data21 = [] # pd.concat takes a list of dataframes as an agrument
data20 = [] # pd.concat takes a list of dataframes as an agrument
#https://stackoverflow.com/questions/41857659/python-pandas-add-filename-column-csv
#https://stackoverflow.com/questions/9234560/find-all-csv-files-in-a-directory-using-python
for csv in csvlist21new:
    frame = pd.read_csv(csv)
    datestring = path.basename(csv)
    curDate = datestring.replace('.csv', '')
    frame['date'] = curDate
    splitDate = curDate.split('-')
    frame['month'] = splitDate[0]
    frame['day'] = splitDate[1]
    frame['year'] = splitDate[2]
    cols=['year','month','day']
    frame['ymd'] = frame[cols].apply(lambda x: '-'.join(x.values.astype(str)), axis="columns")
#     frame['ymd']=pd.to_datetime(frame['ymd'])
    data21.append(frame)

######### THE SAME FOR 2020
for csv in csvlist20new:
    frame = pd.read_csv(csv)
    datestring = path.basename(csv)
    curDate = datestring.replace('.csv', '')
    frame['date'] = curDate
    splitDate = curDate.split('-')
    frame['month'] = splitDate[0]
    frame['day'] = splitDate[1]
    frame['year'] = splitDate[2]
    cols=['year','month','day']
    frame['ymd'] = frame[cols].apply(lambda x: '-'.join(x.values.astype(str)), axis="columns")
#     frame['ymd']=pd.to_datetime(frame['ymd'])
    data20.append(frame)

# combine all csvs into one csv
# add date to each respective file
bigframe21 = pd.concat(data21, ignore_index=True) #dont want pandas to try an align row indexes


# list comprehensions
bigframe21['region'] = [fiveRegion(x) for x in bigframe21['Province_State']]
# Delete rows where region is 'not a region'
# This deletion is completed by "selecting" rows where regions are non 'not a region'
bigframe21 = bigframe21.loc[bigframe21["region"] != 'Not a region']

bigframe21['FIPS'] = [int(x) for x in bigframe21['FIPS']]

# cleanup
bigframe21 = bigframe21.rename({"Province_State": "State", "Country_Region":"Country"}, axis='columns')


###### THE SAME for 2020
bigframe20 = pd.concat(data20, ignore_index=True) #dont want pandas to try an align row indexes


# list comprehensions
bigframe20['region'] = [fiveRegion(x) for x in bigframe20['Province_State']]
# Delete rows where region is 'not a region'
# This deletion is completed by "selecting" rows where regions are non 'not a region'
bigframe20 = bigframe20.loc[bigframe20["region"] != 'Not a region']

bigframe20['FIPS'] = [int(x) for x in bigframe20['FIPS']]

# cleanup
bigframe20 = bigframe20.rename({"Province_State": "State", "Country_Region":"Country"}, axis='columns')

# df.to_csv("total.csv", index=False)

colorBrewer = alt.Color('region:N',
                            scale=alt.Scale(domain=[
                                'Midwest',
                                'Northeast',
                                'Southeast',
                                'Southwest',
                                'West'
                            ],range=['#edf8fb','#b2e2e2','#66c2a4','#2ca25f','#006d2c']))

states = alt.topo_feature(data.us_10m.url, 'states')

map1= alt.Chart(states).mark_geoshape(
    fill='#e8e4f3', stroke='black', strokeWidth=1
).project(
    type='albersUsa'
).properties(
    width=1000,
    height=650
)

# map1
click = alt.selection_single(fields=['State'], bind='legend')

covid21= alt.Chart(bigframe21).mark_circle().transform_filter(
#     {'not': alt.FieldOneOfPredicate(field='Province_State', oneOf=["Diamond Princess", "Grand Princess", "Puerto Rico", "Guam", "Virgin Islands"])}
  {'not': alt.FieldEqualPredicate(field='region', equal="Not a region")}  
).encode(
    longitude='Long_:Q',
    latitude='Lat:Q',
    color=alt.Color('region:N', scale=alt.Scale(scheme='viridis')),
    size=alt.Size('Confirmed', 
#                   scale=alt.Scale(domain=[-1, 200], range=[10,400])
                    scale=alt.Scale(range=[100, 3000]),
                    legend=None
                 ),
    tooltip=['State:N','Confirmed:Q','Deaths:Q'],
#     opacity=alt.condition(click, alt.value(1), alt.value(0.3))
).properties(width=1000,height=650,title='Confirmed Cases 2020')


# full map
# testArea = alt.layer(areachart, lineChart).add_selection(month_select).transform_filter(month_select).resolve_scale(y='independent', color='independent').properties(width=600, height=600).interactive()

covid20= alt.Chart(bigframe20).mark_circle().transform_filter(
#     {'not': alt.FieldOneOfPredicate(field='Province_State', oneOf=["Diamond Princess", "Grand Princess", "Puerto Rico", "Guam", "Virgin Islands"])}
  {'not': alt.FieldEqualPredicate(field='region', equal="Not a region")}  
).encode(
    longitude='Long_:Q',
    latitude='Lat:Q',
    color=alt.Color('region:N', scale=alt.Scale(scheme='viridis')),
    size=alt.Size('Confirmed', 
#                   scale=alt.Scale(domain=[-1, 200], range=[10,400])
                    scale=alt.Scale(range=[100, 3000]),
                    legend=None
                 ),
    tooltip=['State:N','Confirmed:Q','Deaths:Q'],
#     opacity=alt.condition(click, alt.value(1), alt.value(0.3))
).properties(width=1000,height=650,title='Confirmed Cases 2020')

# (map1 + covid21) | (map1 + covid20)
(map1 + covid21) 
(map1 + covid20)

# without reset index had an issue with hierarchical indices
# solved via
## https://stackoverflow.com/questions/32059397/pandas-groupby-without-turning-grouped-by-column-into-index
df_new21 = bigframe21.groupby(['State','FIPS'])[['Deaths','Recovered','Confirmed','region']].max().reset_index()
# df_new += bigframe.groupby('State')['Confirmed'].sum()
df_new21.head(5)
## same for 2020
df_new20 = bigframe20.groupby(['State','FIPS'])[['Deaths','Recovered','Confirmed','region']].max().reset_index()
# df_new += bigframe.groupby('State')['Confirmed'].sum()
df_new20.head(2)

## make dataframes that organise 2021 and 2020 by the month
df_months21 = bigframe21.groupby(['State','FIPS','month'])[['Deaths','Recovered','Confirmed','region','ymd']].max().reset_index()
df_months20 = bigframe20.groupby(['State','FIPS','month'])[['Deaths','Recovered','Confirmed','region','ymd']].max().reset_index()

### list comprehension to change from aggregated total to running totals
# df_months21 = df_months21.groupby(level=0).diff().fillna(df_months21).reset_index()
cum_columns = ['Deaths', 'Confirmed']

df_months21 = df_months21.merge(
    df_months21.groupby('State')[cum_columns].diff(),
    left_index=True, right_index=True, suffixes=['', '_uncum']
).fillna({'{}_uncum'.format(cum_column): df_months21[cum_column] for cum_column in cum_columns})

# print(result)
df_months21region = bigframe21.groupby(['month','region'])[['Deaths','Recovered','Confirmed','ymd']].max().reset_index()
# print(df_months21.groupby(['region', 'month','Confirmed']).sum().index)
df_months21state = df_months21.groupby(['month','State'])[['Deaths','Recovered','Confirmed','ymd','Deaths_uncum']].max().reset_index()
df_months21.tail(20)


### heatmap data
## 2021
biguncum21 = bigframe21.merge(
    bigframe21.groupby('State')[cum_columns].diff(),
    left_index=True, right_index=True, suffixes=['', '_uncum']
).fillna({'{}_uncum'.format(cum_column): df_months21[cum_column] for cum_column in cum_columns})
##2020
biguncum20 = bigframe20.merge(
    bigframe20.groupby('State')[cum_columns].diff(),
    left_index=True, right_index=True, suffixes=['', '_uncum']
).fillna({'{}_uncum'.format(cum_column): df_months21[cum_column] for cum_column in cum_columns})
biguncum20.tail()
State Country Last_Update Lat Long_ Confirmed Deaths Recovered Active FIPS ... date month day year ymd Total_Test_Results Case_Fatality_Ratio region Deaths_uncum Confirmed_uncum
15325 Virginia US 2021-01-01 05:30:27 37.7693 -78.1700 349584 5032 30707.0 313845.0 51 ... 12-31-2020 12 31 2020 2020-12-31 4255991.0 1.439425 Southeast 48.0 5239.0
15326 Washington US 2021-01-01 05:30:27 47.4009 -121.4905 246752 3461 NaN NaN 53 ... 12-31-2020 12 31 2020 2020-12-31 3805390.0 1.402623 West 41.0 4422.0
15327 West Virginia US 2021-01-01 05:30:27 38.4912 -80.9545 85334 1338 59508.0 24488.0 54 ... 12-31-2020 12 31 2020 2020-12-31 1514520.0 1.567957 Southeast 20.0 1109.0
15328 Wisconsin US 2021-01-01 05:30:27 44.2685 -89.6165 520438 5242 447500.0 67696.0 55 ... 12-31-2020 12 31 2020 2020-12-31 5348488.0 1.007229 Midwest 50.0 4212.0
15329 Wyoming US 2021-01-01 05:30:27 42.7560 -107.3025 44409 438 42570.0 1401.0 56 ... 12-31-2020 12 31 2020 2020-12-31 501784.0 0.986287 West 33.0 276.0

5 rows × 28 columns

brush = alt.selection(type='interval', encodings=['x'])

base21 = alt.Chart(df_months21).encode(
    alt.X('monthdate(ymd):O', title='Date'),
    alt.Y('sum(Confirmed):Q', title='Confirmed Cases', scale=alt.Scale(domain=[0,16000000]), axis=alt.Axis(labels=False, title=None)),
    alt.Color('region:N', title='Region', scale=alt.Scale(scheme='viridis'))
).properties(
    width=1500,
    height=1000,
    title='Confirmed cases'
)

upper21 = base21.encode(
    alt.X('monthdate(ymd):O', title='Date', scale=alt.Scale(domain=brush))
)

lower21 = base21.properties(
    height=200
).add_selection(brush)

base20 = alt.Chart(df_months20).encode(
    alt.X('monthdate(ymd):O', title='Date'),
    alt.Y('sum(Confirmed):Q', title='Confirmed Cases', scale=alt.Scale(domain=[0,16000000])),
    alt.Color('region:N', title='Region', scale=alt.Scale(scheme='viridis'))
).properties(
    width=1500,
    height=1000,
    title='Confirmed cases'
)


upper20 = base20.encode(
    alt.X('monthdate(ymd):O', title='Date', scale=alt.Scale(domain=brush))
)

lower20 = base20.properties(
    height=200
).add_selection(brush)

chart21line = alt.vconcat(upper21.mark_line(),lower21.mark_area()).resolve_scale(y='independent',color='independent')
chart20line = alt.vconcat(upper20.mark_line(),lower20.mark_area()).resolve_scale(y='independent',color='independent')

upper21clean = base21.encode(
    alt.X('month(ymd):O', title='Date')
)
upper20clean = base20.encode(
    alt.X('month(ymd):O', title='Date')
)
# alt.hconcat(
#     upper20clean.mark_line(strokeWidth=8),
#     upper21clean.mark_line(strokeWidth=8)).resolve_scale(y='shared').configure_legend(
#     titleFontSize=40,
#     labelFontSize=34,
#     symbolStrokeWidth=40).configure_title(
#     fontSize=60).configure_axis(
#     labelFontSize=34,
#     titleFontSize=38
# )

# select a point for which to provide details-on-demand
label = alt.selection_single(
    encodings=['x'], # limit selection to x-axis value
    on='mouseover',  # select on mouseover events
    nearest=True,    # select data point nearest the cursor
    empty='none'     # empty selection includes no data points
)

# define our base line chart of stock prices
base = alt.Chart().mark_line().encode(
    alt.X('month(ymd):O', title='Date'),
    alt.Y('sum(Confirmed):Q', title='Confirmed Cases',
          scale=alt.Scale(domain=[0,16000000]),
         ),
    alt.Color('region:N', title='Region', scale=alt.Scale(scheme='viridis'))
)

layer2= alt.layer(
    base, # base line chart
    
    # add a rule mark to serve as a guide line
    alt.Chart().mark_rule(color='#aaa').encode(
        x='month(ymd):O'
    ).transform_filter(label),
    
    # add circle marks for selected time points, hide unselected points
    base.mark_circle().encode(
        opacity=alt.condition(label, alt.value(1), alt.value(0))
    ).add_selection(label),

    # add white stroked text to provide a legible background for labels
    base.mark_text(align='left', dx=5, dy=-5, stroke='white', strokeWidth=2).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),

    # add text labels for stock prices
    base.mark_text(align='left', dx=5, dy=-5).encode(
        text='sum(Confirmed):Q',
        
    ).transform_filter(label),
    
    data=df_months21
).properties(
    width=900, height=750,
    title='Confirmed cases'
)

layer1= alt.layer(
    base, # base line chart
    
    # add a rule mark to serve as a guide line
    alt.Chart().mark_rule(color='#aaa').encode(
        x='month(ymd):O'
    ).transform_filter(label),
    
    # add circle marks for selected time points, hide unselected points
    base.mark_circle().encode(
        opacity=alt.condition(label, alt.value(1), alt.value(0))
    ).add_selection(label),

    # add white stroked text to provide a legible background for labels
    base.mark_text(align='left', dx=5, dy=-5, stroke='white', strokeWidth=2).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),

    # add text labels for stock prices
    base.mark_text(align='left', dx=5, dy=-5).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),
    
    data=df_months20
).properties(
    width=900, height=750,
    title='Confirmed cases'
)

# lineLayers = alt.hconcat(layer1,layer2).resolve_scale(y='shared').configure_legend(
#     titleFontSize=40,
#     labelFontSize=34,
#     symbolStrokeWidth=20).configure_title(
#     fontSize=60).configure_axis(
#     labelFontSize=34,
#     titleFontSize=38
# )
alt.layer(
    base, # base line chart
    
    # add a rule mark to serve as a guide line
    alt.Chart().mark_rule(color='#aaa').encode(
        x='month(ymd):O'
    ).transform_filter(label),
    
    # add circle marks for selected time points, hide unselected points
    base.mark_circle().encode(
        opacity=alt.condition(label, alt.value(1), alt.value(0))
    ).add_selection(label),

    # add white stroked text to provide a legible background for labels
    base.mark_text(align='left', dx=5, dy=-5, stroke='white', strokeWidth=2).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),

    # add text labels for stock prices
    base.mark_text(align='left', dx=5, dy=-5).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),
    
    data=df_months20
).properties(
    width=900, height=750,
    title='Confirmed cases 2020'
)
alt.layer(
    base, # base line chart
    
    # add a rule mark to serve as a guide line
    alt.Chart().mark_rule(color='#aaa').encode(
        x='month(ymd):O'
    ).transform_filter(label),
    
    # add circle marks for selected time points, hide unselected points
    base.mark_circle().encode(
        opacity=alt.condition(label, alt.value(1), alt.value(0))
    ).add_selection(label),

    # add white stroked text to provide a legible background for labels
    base.mark_text(align='left', dx=5, dy=-5, stroke='white', strokeWidth=2).encode(
        text='sum(Confirmed):Q'
    ).transform_filter(label),

    # add text labels for stock prices
    base.mark_text(align='left', dx=5, dy=-5).encode(
        text='sum(Confirmed):Q',
        
    ).transform_filter(label),
    
    data=df_months21
).properties(
    width=900, height=750,
    title='Confirmed cases 2021'
)

deaths21 = alt.Chart(df_months21).mark_bar().encode(
    alt.X('month(ymd):O', title='Month'),
    alt.Y('max(Deaths):Q', title='Deaths', scale=alt.Scale(domain=[0,320000]), axis=alt.Axis(labels=False, title=None)),
    alt.Color('region:N', title='Region', scale=alt.Scale(scheme='viridis')),
#     tooltip=['State:N']
).properties(
    width=900, height=750,
    title='Cumulative Deaths by US Region'
)

deaths20 = alt.Chart(df_months20).mark_bar().encode(
    alt.X('month(ymd):O', title='Month'),
    alt.Y('max(Deaths):Q', title='Deaths', scale=alt.Scale(domain=[0,320000])),
    alt.Color('region:N', title='Region', scale=alt.Scale(scheme='viridis')),
#     tooltip=['State:N']
).properties(
    width=900, height=750,
    title='Cumulative Deaths by US Region'
)


# (deaths20 | deaths21).resolve_scale(y='shared').configure_legend(
#     titleFontSize=40,
#     labelFontSize=34,
#     symbolStrokeWidth=40,
#     symbolSize=400).configure_title(
#     fontSize=60,).configure_axis(
#     labelFontSize=34,
#     titleFontSize=38
# )

# https://altair-viz.github.io/user_guide/transform/lookup.html
chloroYear21 = alt.Chart(states).mark_geoshape(stroke='black', strokeWidth=1).encode(
#     color='Deaths:Q',
    color=alt.Color('Deaths:Q', scale=alt.Scale(scheme='viridis')),
    tooltip=['State:N','Confirmed:Q','Recovered:Q','Deaths:Q'],
).transform_lookup(
    # the value in the data url I will map to, basically the point that joins the 2 data sources, must be the same
    lookup='id',
    # linking id from https://raw.githubusercontent.com/vega/vega-datasets/next/data/us-10m.json
    # with FIPS from the dataframe
    from_=alt.LookupData(data=df_new21, key='FIPS', fields=['Deaths','State','Confirmed','Recovered'])
).project(
    type='albersUsa'
).properties(
    width=900, height=750,
    title="COVID-19 stats for 2021"
)

# same for 2020
# https://altair-viz.github.io/user_guide/transform/lookup.html
chloroYear20 = alt.Chart(states).mark_geoshape(stroke='black', strokeWidth=1).encode(
#     color='Deaths:Q',
    color=alt.Color('Deaths:Q', scale=alt.Scale(scheme='viridis')),
    tooltip=['State:N','Confirmed:Q','Recovered:Q','Deaths:Q'],
).transform_lookup(
    # the value in the data url I will map to, basically the point that joins the 2 data sources, must be the same
    lookup='id',
    # linking id from https://raw.githubusercontent.com/vega/vega-datasets/next/data/us-10m.json
    # with FIPS from the dataframe
    from_=alt.LookupData(data=df_new20, key='FIPS', fields=['Deaths','State','Confirmed','Recovered'])
).project(
    type='albersUsa'
).properties(
    width=900, height=750,
    title="COVID-19 stats for 2020"
)

# alt.vconcat(chloroYear21,chloroYear20)
# (chloroYear20 | chloroYear21).resolve_scale(y='shared').configure_legend(
#     titleFontSize=34,
#     labelFontSize=34,
#     symbolStrokeWidth=60,
#     symbolSize=300).configure_title(
#     fontSize=50).configure_axis(
#     labelFontSize=20,
#     titleFontSize=28
# )


heatmap21 = alt.Chart(bigframe21).mark_rect().encode(
    alt.X('month(date):O', title='Month'),
    alt.Y('State:N', title='State', axis=alt.Axis(labels=False, title=None)),
    alt.Color('Deaths:Q', title='Deaths', scale=alt.Scale(scheme='viridis'), legend=alt.Legend(title='Total')),
    tooltip=['region:N','State:N','Deaths:Q']
).properties(title= 'Cumulative Deaths by State', width=900, height=750)

heatmap20 = alt.Chart(bigframe20).mark_rect().encode(
    alt.X('month(ymd):O', title='date'),
    alt.Y('State:N', title='State'),
    alt.Color('Deaths:Q', title='Deaths', scale=alt.Scale(scheme='viridis'), legend=alt.Legend(title='Total')),
    tooltip=['Deaths:Q']
).properties(title='Cumulative Deaths by State', width=900, height=750)

# (heatmap20 | heatmap21).resolve_scale(y='shared').configure_legend(
#     titleFontSize=40,
#     labelFontSize=34,
#     symbolStrokeWidth=40).configure_title(
#     fontSize=60).configure_axis(
#     labelFontSize=24,
#     titleFontSize=38
# )
chloroLayers = alt.hconcat(chloroYear20,chloroYear21).resolve_scale(y='shared')
lineLayers = alt.hconcat(layer1,layer2).resolve_scale(y='shared')
barLayers = alt.hconcat(deaths20,deaths21).resolve_scale(y='shared')
heatmapLayers = alt.hconcat(heatmap20, heatmap21).resolve_scale(y='shared')
alt.hconcat(chloroYear20,chloroYear21).resolve_scale(y='shared').configure_legend(
    titleFontSize=40,
    labelFontSize=34,
    symbolStrokeWidth=20).configure_title(
    fontSize=60).configure_axis(
    labelFontSize=20,
    titleFontSize=28
)
#.show() exports to localhost and displays
alt.hconcat(layer1,layer2).resolve_scale(y='shared').configure_legend(
    titleFontSize=40,
    labelFontSize=34,
    symbolStrokeWidth=20).configure_title(
    fontSize=60).configure_axis(
    labelFontSize=20,
    titleFontSize=28
)
alt.hconcat(deaths20,deaths21).resolve_scale(y='shared').configure_legend(
    titleFontSize=40,
    labelFontSize=34,
    symbolStrokeWidth=20).configure_title(
    fontSize=60).configure_axis(
    labelFontSize=20,
    titleFontSize=28
)
alt.hconcat(heatmap20, heatmap21).resolve_scale(y='shared').configure_legend(
    titleFontSize=40,
    labelFontSize=34,
    symbolStrokeWidth=20).configure_title(
    fontSize=60).configure_axis(
    labelFontSize=20,
    titleFontSize=28
)